package com.example.netty.websocket;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.stream.ChunkedWriteHandler;

public class MyServer {
    public static void main(String[] args) {
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workGroup = new NioEventLoopGroup();

        try {
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(bossGroup, workGroup)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        ChannelPipeline pipeline = ch.pipeline();
                        // 基于 http 协议，使用 http 的编码和解码器
                        pipeline.addLast(new HttpServerCodec())
                                // 以块方式写，添加 chunkedwrite 处理器
                                .addLast(new ChunkedWriteHandler())
                                /**
                                 * 说明
                                 * 1.http 数据在传输过程中是分段，HttpObjectAggregator
                                 * 可以将多个断聚合
                                 * 2.当浏览器发送大量数据时，就会发出多次 http 请求
                                 */
                                .addLast(new HttpObjectAggregator(8192))
                                /**
                                 * 1.对于 webSocket，它的数据是以帧（frame）形式传递
                                 * 2.可以看到 WebSocketFrame 下面有六个子类
                                 * 3.浏览器请求时 ws://localhost:7000/hello 表示请求的 uri
                                 * 4.WebSocketServerProtocolHandler 核心功能将 http 协议升级为 ws 协议
                                 * 保持长链接
                                 * 5. 是通过一个状态码 101
                                 */
                                .addLast(new WebSocketServerProtocolHandler("/hello"))
                                /**
                                 * 自定义的 handler，处理业务
                                 */
                                .addLast(new MyTextWebSocketFrameHandler());
                    }
                });
            ChannelFuture channelFuture = serverBootstrap.bind(7000).sync();
            channelFuture.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            bossGroup.shutdownGracefully();
            workGroup.shutdownGracefully();
        }

    }
}
